-- Desc: 根据退款的结果，处理商品库存
-- 退款结果：
-- 1.退款操作成功，还原商品库存
-- 2.退款操作失败，仅删除退款记录，不需要更改库存



-- ================ 以下为函数， 不属于主流程 ================
local function containsValue(list, value)
    for i = 1, #list do
        if list[i] == value then
            return false
        end
    end
    return true
end

-- ================ 开始退款还原库存流程 ================
local params = {}
-- 用于批量获取sku库存和退款操作时间的key集合
local mgetSkuKeys = {}
-- sku键数组
local skuKey = {}
-- refundId列表
local refundIds = {}
local refundId = ""
local time = ""
-- 步骤一    入参 KEYS skuId_退款数量_库存id_退款id_时间_操作_默认仓库id   skuId_退款数量_库存id_退款id_时间_操作_默认仓库id...
for index, paramStr in ipairs(KEYS) do
    -- {skuId，退款数量，库存id，退款id，时间，操作，默认仓库id}
    local param = {}
    for value in string.gmatch(paramStr, "%d+") do
        table.insert(param, value)
    end
    table.insert(params, param)
    if refundId == "" then
        refundId = param[4]
        time = param[5]
    end

    -- 避免一个sku同时进行多个操作时，查询和计算的库存数据操作，所以这里要对区域库存和总库存的key去重
    local key = param[1].."_"..param[3]
    -- 区域库存被删除后，使用默认库存
    if tonumber(param[7]) > 0 then
        key = param[1].."_"..param[7]
    end
    local skuId = tonumber(param[1])
    -- 数组没有的sku数组再添加到数组，skuKey用于批量查询后的sku数据绑定
    -- 区域库存去重
    if param[3] ~= "0" and containsValue(skuKey, key) then
        -- sku区域库存key格式： key名称:skuId_仓库id
        table.insert(mgetSkuKeys, "mall4j_product:sku_sock:"..key)
        table.insert(skuKey, key)
    end
    -- 总库存去重
    if containsValue(skuKey, skuId) then
        -- sku总库存key格式： key名称:skuId
        table.insert(mgetSkuKeys, "mall4j_product:sku_sock:"..skuId)
        -- 用数字类型区分总库存
        table.insert(skuKey, skuId)
    end
end
-- 查询退款最后一次操作的退款时间
for i = 1,#params do
    local param = params[i]
    if containsValue(refundIds, param[4]) then
        -- 退款操作时间：key格式： key名称:refundId
        table.insert(mgetSkuKeys, "mall4j_product:order_refund_time:"..param[4])
        table.insert(refundIds, param[4])
    end
end


-- 下面通过mget获取所有key的值，call后面是可变长参数，unpack是将数组变成可变长参数
local skuStr = redis.call('mget', unpack(mgetSkuKeys));

-- 拆分mget中获取到的sku库存信息。  skuStocks： map<skukey, sku库存数据>   skukey：区域库存=skuId_仓库id; 总库存=skuId
local skuStocks = {}
for index, key in ipairs(skuKey) do
    -- {可售库存数量, 锁定库存数量, 销量, sku库存状态}
    local skuStock = {}
    for value in string.gmatch(skuStr[index], "%d+") do
        table.insert(skuStock, tonumber(value))
    end
    -- sku库存列表
    skuStocks[key] = skuStock
end

local skuLength = # skuKey
local refundList = {}
for index, key in ipairs(refundIds) do
    -- {可售库存数量, 锁定库存数量, 销量, sku库存状态}
    local value = skuStr[index + skuLength]
    if not value then
        value = false
    end
    -- sku库存列表
    refundList[key] = value
end
-- 初始化
refundIds = {}


local result = ""
local updateNum = 0
--按照订单来还原库存
for i = 1,#params do
    -- skuId_refundNum(退货数量)_库存id
    local param = params[i]

    -- 删除锁定标记 key-退款id_skuId_库存id
    local isDelete = redis.call('del',"mall4j_product:order_refund_sku_lock:"..param[4].."_"..param[1].."_"..param[3].."_"..param[5])
    -- 删除锁定标记成功才进行还原库存，让方法幂等, 没有删除锁定标记就跳过本次循环
    if isDelete > 0 then
        local refundTime = refundList[param[4]]
        local skuStockPointId = param[3]
        -- 区域库存被删除后，使用默认库存
        if tonumber(param[7]) > 0 then
            skuStockPointId = param[7]
        end
        local last = refundTime == param[5]
        if param[6] == "1" and last then
            -- 可售库存数量_锁定库存数量_销量_sku库存状态
            -- 确认
            local skuPointStock = skuStocks[param[1].."_"..skuStockPointId]
            local skuStock = skuStocks[tonumber(param[1])]
            local changeStock = tonumber(param[2])
            -- 成功
            if param[3] ~= "0" then
                if param[7] == "0" then
                    -- 减少销量
                    skuPointStock[3] = tonumber(skuPointStock[3]) - changeStock
                end
                -- 退款处理失败 - 减少销量, 增加可售卖库存
                skuPointStock[1] = tonumber(skuPointStock[1]) + changeStock
            end
            skuStock[3] = tonumber(skuStock[3]) - changeStock
            skuStock[1] = tonumber(skuStock[1]) + changeStock
            -- 记录
            if param[3] ~= "0" then
                result = result..param[4].."_"..param[3].."_"..param[1].."_"..skuPointStock[1]..","
            end
            -- 退款id_仓库id_skuId_剩余库存,订单id_仓库id_skuId_剩余库存...
            result = result..param[4].."_"..param[3].."_"..param[1].."_"..skuStock[1]..","
        end

        if last and containsValue(refundIds, param[4]) then
            table.insert(refundIds, param[4])
        end
        updateNum = updateNum + 1
    end
end

for index, refundIdStr in ipairs(refundIds) do
    redis.call('del', "mall4j_product:order_refund_time:"..refundIdStr)
end


-- 用于批量设置sku库存信息的key和value集合
local msetSkuKV = {}
if updateNum > 0 then
    for index, key in ipairs(skuKey) do
        -- 库存信息 {可售库存数量, 锁定库存数量, 销量, sku库存状态}
        local skuStock = skuStocks[key]
        -- mset sku库存key   总库存格式：  key名称:skuId； 区域库存格式：  key名称:skuId_仓库id
        table.insert(msetSkuKV, "mall4j_product:sku_sock:"..key)
        -- mset sku库存value   格式：  可售库存数量_锁定库存数量_销量_sku库存状态
        table.insert(msetSkuKV, skuStock[1].."_"..skuStock[2].."_"..skuStock[3].."_"..skuStock[4])
    end
    -- 修改回redis
    redis.call('mset',unpack(msetSkuKV))
end


return result